home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / lwlib / lwlib-Xlw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-06  |  11.1 KB  |  417 lines

  1. /* The lwlib interface to "xlwmenu" menus.
  2.    Copyright (C) 1992, 1994 Lucid, Inc.
  3.  
  4. This file is part of the Lucid Widget Library.
  5.  
  6. The Lucid Widget Library is free software; you can redistribute it and/or 
  7. modify it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. The Lucid Widget Library is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdlib.h> /* for abort () */
  21. #include <limits.h>
  22.  
  23. #include "lwlib-Xlw.h"
  24. #include <X11/StringDefs.h>
  25. #include <X11/IntrinsicP.h>
  26. #include <X11/ObjectP.h>
  27. #include <X11/CompositeP.h>
  28. #include <X11/Shell.h>
  29. #include "xlwmenu.h"
  30. #include "xlwscrollbar.h"
  31.  
  32. /* Menu callbacks */
  33.  
  34. static void
  35. pre_hook (Widget w, XtPointer client_data, XtPointer call_data)
  36. {
  37.   widget_instance* instance = (widget_instance*)client_data;
  38.   widget_value* val;
  39.   
  40.   if (w->core.being_destroyed)
  41.     return;
  42.  
  43.   val = lw_get_widget_value_for_widget (instance, w);
  44. #if 0
  45.   /* #### - this code used to (for some random back_asswards reason) pass
  46.   the expression below in the call_data slot.  For incremental menu
  47.   construction, this needs to go.  I can't even figure out why it was done
  48.   this way in the first place...it's just a historical wierdism. --Stig */
  49.   call_data = (val ? val->call_data : NULL);
  50. #endif 
  51.   if (val && val->call_data)
  52.     abort();            /* #### - the call_data for the top_level
  53.                    "menubar" widget_value used to be passed
  54.                    back to the pre_hook. */
  55.  
  56.   if (instance->info->pre_activate_cb)
  57.     instance->info->pre_activate_cb (w, instance->info->id, call_data);
  58. }
  59.  
  60. static void
  61. pick_hook (Widget w, XtPointer client_data, XtPointer call_data)
  62. {
  63.   widget_instance* instance = (widget_instance*)client_data;
  64.   widget_value* contents_val = (widget_value*)call_data;
  65.   widget_value* widget_val;
  66.   XtPointer widget_arg;
  67.   LWLIB_ID id;
  68.   lw_callback post_activate_cb;
  69.  
  70.   if (w->core.being_destroyed)
  71.     return;
  72.  
  73.   /* Grab these values before running any functions, in case running
  74.      the selection_cb causes the widget to be destroyed. */
  75.   id = instance->info->id;
  76.   post_activate_cb = instance->info->post_activate_cb;
  77.  
  78.   widget_val = lw_get_widget_value_for_widget (instance, w);
  79.   widget_arg = widget_val ? widget_val->call_data : NULL;
  80.  
  81.   if (instance->info->selection_cb &&
  82.       contents_val &&
  83.       contents_val->enabled &&
  84.       !contents_val->contents)
  85.     instance->info->selection_cb (w, id, contents_val->call_data);
  86.  
  87.   if (post_activate_cb)
  88.     post_activate_cb (w, id, widget_arg);
  89. }
  90.  
  91. /* creation functions */
  92. #ifdef MENUBARS_LUCID
  93. static Widget
  94. xlw_create_menubar (widget_instance* instance)
  95. {
  96.   Widget widget =
  97.     XtVaCreateWidget (instance->info->name, xlwMenuWidgetClass,
  98.               instance->parent,
  99.               XtNmenu, instance->info->val,
  100.               0);
  101.   XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
  102.   XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
  103.   return widget;
  104. }
  105.  
  106. static Widget
  107. xlw_create_popup_menu (widget_instance* instance)
  108. {
  109.   Widget popup_shell =
  110.     XtCreatePopupShell (instance->info->name, overrideShellWidgetClass,
  111.             instance->parent, NULL, 0);
  112.   
  113.   Widget widget = 
  114.     XtVaCreateManagedWidget ("popup", xlwMenuWidgetClass,
  115.                  popup_shell,
  116.                  XtNmenu, instance->info->val,
  117.                  XtNhorizontal, False,
  118.                  0);
  119.  
  120.   XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
  121.  
  122.   return popup_shell;
  123. }
  124. #endif /* MENUBARS_LUCID */
  125.  
  126. #ifdef SCROLLBARS_LUCID
  127. static void
  128. xlw_scrollbar_callback (Widget widget, XtPointer closure, XtPointer call_data)
  129. {
  130.   widget_instance *instance = (widget_instance *) closure;
  131.   LWLIB_ID id;
  132.   XlwScrollBarCallbackStruct *data =
  133.     (XlwScrollBarCallbackStruct *) call_data;
  134.   scroll_event event_data;
  135.   scrollbar_values *val =
  136.     (scrollbar_values *) instance->info->val->scrollbar_data;
  137.   double percent;
  138.  
  139.   if (!instance || widget->core.being_destroyed)
  140.     return;
  141.  
  142.   id = instance->info->id;
  143.  
  144.   percent = (double) (data->value - 1) / (double) (INT_MAX - 1);
  145.   event_data.slider_value =
  146.     (int) (percent * (double) (val->maximum - val->minimum)) + val->minimum;
  147.  
  148.   if (event_data.slider_value > (val->maximum - val->slider_size))
  149.     event_data.slider_value = val->maximum - val->slider_size;
  150.   else if (event_data.slider_value < val->minimum)
  151.     event_data.slider_value = val->minimum;
  152.  
  153.   if (data->event)
  154.     {
  155.       switch (data->event->xany.type)
  156.     {
  157.     case KeyPress:
  158.     case KeyRelease:
  159.       event_data.time = data->event->xkey.time;
  160.       break;
  161.     case ButtonPress:
  162.     case ButtonRelease:
  163.       event_data.time = data->event->xbutton.time;
  164.       break;
  165.     case MotionNotify:
  166.       event_data.time = data->event->xmotion.time;
  167.       break;
  168.     case EnterNotify:
  169.     case LeaveNotify:
  170.       event_data.time = data->event->xcrossing.time;
  171.       break;
  172.     default:
  173.       event_data.time = 0;
  174.       break;
  175.     }
  176.     }
  177.   else
  178.     event_data.time = 0;
  179.  
  180.   switch (data->reason)
  181.     {
  182.     case XmCR_DECREMENT:
  183.       event_data.action = SCROLLBAR_LINE_UP;
  184.       break;
  185.     case XmCR_INCREMENT:
  186.       event_data.action = SCROLLBAR_LINE_DOWN;
  187.       break;
  188.     case XmCR_PAGE_DECREMENT:
  189.       event_data.action = SCROLLBAR_PAGE_UP;
  190.       break;
  191.     case XmCR_PAGE_INCREMENT:
  192.       event_data.action = SCROLLBAR_PAGE_DOWN;
  193.       break;
  194.     case XmCR_TO_TOP:
  195.       event_data.action = SCROLLBAR_TOP;
  196.       break;
  197.     case XmCR_TO_BOTTOM:
  198.       event_data.action = SCROLLBAR_BOTTOM;
  199.       break;
  200.     case XmCR_DRAG:
  201.       event_data.action = SCROLLBAR_DRAG;
  202.       break;
  203.     case XmCR_VALUE_CHANGED:
  204.       event_data.action = SCROLLBAR_CHANGE;
  205.       break;
  206.     default:
  207.       event_data.action = SCROLLBAR_CHANGE;
  208.       break;
  209.     }
  210.  
  211.   if (instance->info->pre_activate_cb)
  212.     instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
  213. }
  214.  
  215. /* #### Does not yet support horizontal scrollbars. */
  216. static Widget
  217. xlw_create_scrollbar (widget_instance *instance, int vertical)
  218. {
  219.   Arg al[20];
  220.   int ac = 0;
  221.   Widget scrollbar;
  222.  
  223.   XtSetArg (al[ac], XmNminimum, 1); ac++;
  224.   XtSetArg (al[ac], XmNmaximum, INT_MAX); ac++;
  225.   XtSetArg (al[ac], XmNincrement, 1); ac++;
  226.   XtSetArg (al[ac], XmNpageIncrement, 1); ac++;
  227.   if (vertical)
  228.     {
  229.       XtSetArg (al[ac], XmNorientation, XmVERTICAL); ac++;
  230.     }
  231.   else
  232.     {
  233.       XtSetArg (al[ac], XmNorientation, XmHORIZONTAL); ac++;
  234.     }
  235.  
  236.   scrollbar =
  237.     XtCreateWidget (instance->info->name, xlwScrollBarWidgetClass, instance->parent, al, ac);
  238.  
  239.   XtAddCallback(scrollbar, XmNdecrementCallback, xlw_scrollbar_callback,
  240.         (XtPointer) instance);
  241.   XtAddCallback(scrollbar, XmNdragCallback, xlw_scrollbar_callback,
  242.         (XtPointer) instance);
  243.   XtAddCallback(scrollbar, XmNincrementCallback, xlw_scrollbar_callback,
  244.         (XtPointer) instance);
  245.   XtAddCallback(scrollbar, XmNpageDecrementCallback, xlw_scrollbar_callback,
  246.         (XtPointer) instance);
  247.   XtAddCallback(scrollbar, XmNpageIncrementCallback, xlw_scrollbar_callback,
  248.         (XtPointer) instance);
  249.   XtAddCallback(scrollbar, XmNtoBottomCallback, xlw_scrollbar_callback,
  250.         (XtPointer) instance);
  251.   XtAddCallback(scrollbar, XmNtoTopCallback, xlw_scrollbar_callback,
  252.         (XtPointer) instance);
  253.   XtAddCallback(scrollbar, XmNvalueChangedCallback, xlw_scrollbar_callback,
  254.         (XtPointer) instance);
  255.  
  256.   return scrollbar;
  257. }
  258.  
  259. static Widget
  260. xlw_create_vertical_scrollbar (widget_instance *instance)
  261. {
  262.   return xlw_create_scrollbar (instance, 1);
  263. }
  264.  
  265. static Widget
  266. xlw_create_horizontal_scrollbar (widget_instance *instance)
  267. {
  268.   return xlw_create_scrollbar (instance, 0);
  269. }
  270.  
  271. #endif /* SCROLLBARS_LUCID */
  272.  
  273. static void
  274. xlw_update_scrollbar (widget_instance *instance, Widget widget,
  275.               widget_value *val)
  276. {
  277.   if (val->scrollbar_data)
  278.     {
  279.       scrollbar_values *data = val->scrollbar_data;
  280.       int widget_sliderSize, widget_val;
  281.       int new_sliderSize, new_value;
  282.       double percent;
  283.  
  284.       /*
  285.        * First size and position the scrollbar widget.
  286.        */
  287.       XtVaSetValues (widget,
  288.              XtNx, data->scrollbar_x,
  289.              XtNy, data->scrollbar_y,
  290.              XtNwidth, data->scrollbar_width,
  291.              XtNheight, data->scrollbar_height,
  292.              0);
  293.  
  294.       /*
  295.        * Now the size the scrollbar's slider.
  296.        */
  297.  
  298.       XtVaGetValues (widget,
  299.              XmNsliderSize, &widget_sliderSize,
  300.              XmNvalue, &widget_val,
  301.              0);
  302.  
  303.       percent = (double) data->slider_size /
  304.     (double) (data->maximum - data->minimum);
  305.       percent = (percent > 1.0 ? 1.0 : percent);
  306.       new_sliderSize = (int) ((double) (INT_MAX - 1) * percent);
  307.  
  308.       percent = (double) (data->slider_position - data->minimum) /
  309.     (double) (data->maximum - data->minimum);
  310.       percent = (percent > 1.0 ? 1.0 : percent);
  311.       new_value = (int) ((double) (INT_MAX - 1) * percent);
  312.  
  313.       if (new_sliderSize > (INT_MAX - 1))
  314.     new_sliderSize = INT_MAX - 1;
  315.       if (new_sliderSize < 1)
  316.     new_sliderSize = 1;
  317.  
  318.       if (new_value > (INT_MAX - new_sliderSize))
  319.     new_value = INT_MAX - new_sliderSize;
  320.       else if (new_value < 1)
  321.     new_value = 1;
  322.  
  323.       if (new_sliderSize != widget_sliderSize || new_value != widget_val)
  324.     XlwScrollBarSetValues (widget, new_value, new_sliderSize, 1, 1, False);
  325.     }
  326. }
  327.  
  328. widget_creation_entry 
  329. xlw_creation_table [] =
  330. {
  331. #ifdef MENUBARS_LUCID
  332.   {"menubar", xlw_create_menubar},
  333.   {"popup", xlw_create_popup_menu},
  334. #endif
  335. #ifdef SCROLLBARS_LUCID
  336.   {"vertical-scrollbar",    xlw_create_vertical_scrollbar},
  337.   {"horizontal-scrollbar",    xlw_create_horizontal_scrollbar},
  338. #endif
  339.   {NULL, NULL}
  340. };
  341.  
  342. Boolean
  343. lw_lucid_widget_p (Widget widget)
  344. {
  345.   WidgetClass the_class = XtClass (widget);
  346.   if (the_class == xlwMenuWidgetClass)
  347.     return True;
  348.   if (the_class == xlwScrollBarWidgetClass)
  349.     return True;
  350.   if (the_class == overrideShellWidgetClass)
  351.     return
  352.       XtClass (((CompositeWidget)widget)->composite.children [0])
  353.     == xlwMenuWidgetClass;
  354.   return False;
  355. }
  356.  
  357. void
  358. xlw_update_one_widget (widget_instance* instance, Widget widget,
  359.                widget_value* val, Boolean deep_p)
  360. {
  361.   WidgetClass class;
  362.   XlwMenuWidget mw;
  363.  
  364.   class = XtClass (widget);
  365.  
  366.   if (class == xlwMenuWidgetClass)
  367.     {
  368.     if (XtIsShell (widget))
  369.       mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
  370.     else
  371.       mw = (XlwMenuWidget)widget;
  372.     XtVaSetValues (widget, XtNmenu, val, 0);
  373.     }
  374.   else if( class == xlwScrollBarWidgetClass )
  375.     {
  376.     xlw_update_scrollbar (instance, widget, val);
  377.     }
  378. }
  379.  
  380. void
  381. xlw_update_one_value (widget_instance* instance, Widget widget,
  382.               widget_value* val)
  383. {
  384.   return;
  385. }
  386.  
  387. void
  388. xlw_pop_instance (widget_instance* instance, Boolean up)
  389. {
  390. }
  391.  
  392. void
  393. xlw_popup_menu (Widget widget, XEvent *event)
  394. {
  395.   XlwMenuWidget mw;
  396.  
  397.   if (!XtIsShell (widget))
  398.     return;
  399.  
  400.   if (event->type == ButtonPress || event->type == ButtonRelease)
  401.     {
  402.       mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
  403.       xlw_pop_up_menu (mw, (XButtonPressedEvent *)event);
  404.     }
  405.   else
  406.     abort ();
  407. }
  408.  
  409. /* Destruction of instances */
  410. void
  411. xlw_destroy_instance (widget_instance* instance)
  412. {
  413.   if (instance->widget)
  414.     XtDestroyWidget (instance->widget);
  415. }
  416.  
  417.